using System;
namespace MicroMsg.Common.Algorithm
{
	public class DES
	{
		public const int ENCRYPTION = 1;
		public const int DECRYPTION = 2;
		private static int[] PC1_TABLE = new int[]
		{
			56,
			48,
			40,
			32,
			24,
			16,
			8,
			0,
			57,
			49,
			41,
			33,
			25,
			17,
			9,
			1,
			58,
			50,
			42,
			34,
			26,
			18,
			10,
			2,
			59,
			51,
			43,
			35,
			62,
			54,
			46,
			38,
			30,
			22,
			14,
			6,
			61,
			53,
			45,
			37,
			29,
			21,
			13,
			5,
			60,
			52,
			44,
			36,
			28,
			20,
			12,
			4,
			27,
			19,
			11,
			3
		};
		private static byte[] PC2_TABLE = new byte[]
		{
			13,
			16,
			10,
			23,
			0,
			4,
			2,
			27,
			14,
			5,
			20,
			9,
			22,
			18,
			11,
			3,
			25,
			7,
			15,
			6,
			26,
			19,
			12,
			1,
			40,
			51,
			30,
			36,
			46,
			54,
			29,
			39,
			50,
			44,
			32,
			47,
			43,
			48,
			38,
			55,
			33,
			52,
			45,
			41,
			49,
			35,
			28,
			31
		};
		private static byte[] LOOP_TABLE = new byte[]
		{
			1,
			1,
			2,
			2,
			2,
			2,
			2,
			2,
			1,
			2,
			2,
			2,
			2,
			2,
			2,
			1
		};
		private static byte[] S_BOX = new byte[]
		{
			14,
			4,
			13,
			1,
			2,
			15,
			11,
			8,
			3,
			10,
			6,
			12,
			5,
			9,
			0,
			7,
			0,
			15,
			7,
			4,
			14,
			2,
			13,
			1,
			10,
			6,
			12,
			11,
			9,
			5,
			3,
			8,
			4,
			1,
			14,
			8,
			13,
			6,
			2,
			11,
			15,
			12,
			9,
			7,
			3,
			10,
			5,
			0,
			15,
			12,
			8,
			2,
			4,
			9,
			1,
			7,
			5,
			11,
			3,
			14,
			10,
			0,
			6,
			13,
			15,
			1,
			8,
			14,
			6,
			11,
			3,
			4,
			9,
			7,
			2,
			13,
			12,
			0,
			5,
			10,
			3,
			13,
			4,
			7,
			15,
			2,
			8,
			14,
			12,
			0,
			1,
			10,
			6,
			9,
			11,
			5,
			0,
			14,
			7,
			11,
			10,
			4,
			13,
			1,
			5,
			8,
			12,
			6,
			9,
			3,
			2,
			15,
			13,
			8,
			10,
			1,
			3,
			15,
			4,
			2,
			11,
			6,
			7,
			12,
			0,
			5,
			14,
			9,
			10,
			0,
			9,
			14,
			6,
			3,
			15,
			5,
			1,
			13,
			12,
			7,
			11,
			4,
			2,
			8,
			13,
			7,
			0,
			9,
			3,
			4,
			6,
			10,
			2,
			8,
			5,
			14,
			12,
			11,
			15,
			1,
			13,
			6,
			4,
			9,
			8,
			15,
			3,
			0,
			11,
			1,
			2,
			12,
			5,
			10,
			14,
			7,
			1,
			10,
			13,
			0,
			6,
			9,
			8,
			7,
			4,
			15,
			14,
			3,
			11,
			5,
			2,
			12,
			7,
			13,
			14,
			3,
			0,
			6,
			9,
			10,
			1,
			2,
			8,
			5,
			11,
			12,
			4,
			15,
			13,
			8,
			11,
			5,
			6,
			15,
			0,
			3,
			4,
			7,
			2,
			12,
			1,
			10,
			14,
			9,
			10,
			6,
			9,
			0,
			12,
			11,
			7,
			13,
			15,
			1,
			3,
			14,
			5,
			2,
			8,
			4,
			3,
			15,
			0,
			6,
			10,
			1,
			13,
			8,
			9,
			4,
			5,
			11,
			12,
			7,
			2,
			14,
			2,
			12,
			4,
			1,
			7,
			10,
			11,
			6,
			8,
			5,
			3,
			15,
			13,
			0,
			14,
			9,
			14,
			11,
			2,
			12,
			4,
			7,
			13,
			1,
			5,
			0,
			15,
			10,
			3,
			9,
			8,
			6,
			4,
			2,
			1,
			11,
			10,
			13,
			7,
			8,
			15,
			9,
			12,
			5,
			6,
			3,
			0,
			14,
			11,
			8,
			12,
			7,
			1,
			14,
			2,
			13,
			6,
			15,
			0,
			9,
			10,
			4,
			5,
			3,
			12,
			1,
			10,
			15,
			9,
			2,
			6,
			8,
			0,
			13,
			3,
			4,
			14,
			7,
			5,
			11,
			10,
			15,
			4,
			2,
			7,
			12,
			9,
			5,
			6,
			1,
			13,
			14,
			0,
			11,
			3,
			8,
			9,
			14,
			15,
			5,
			2,
			8,
			12,
			3,
			7,
			0,
			4,
			10,
			1,
			13,
			11,
			6,
			4,
			3,
			2,
			12,
			9,
			5,
			15,
			10,
			11,
			14,
			1,
			7,
			6,
			0,
			8,
			13,
			4,
			11,
			2,
			14,
			15,
			0,
			8,
			13,
			3,
			12,
			9,
			7,
			5,
			10,
			6,
			1,
			13,
			0,
			11,
			7,
			4,
			9,
			1,
			10,
			14,
			3,
			5,
			12,
			2,
			15,
			8,
			6,
			1,
			4,
			11,
			13,
			12,
			3,
			7,
			14,
			10,
			15,
			6,
			8,
			0,
			5,
			9,
			2,
			6,
			11,
			13,
			8,
			1,
			4,
			10,
			7,
			9,
			5,
			0,
			15,
			14,
			2,
			3,
			12,
			13,
			2,
			8,
			4,
			6,
			15,
			11,
			1,
			10,
			9,
			3,
			14,
			5,
			0,
			12,
			7,
			1,
			15,
			13,
			8,
			10,
			3,
			7,
			4,
			12,
			5,
			6,
			11,
			0,
			14,
			9,
			2,
			7,
			11,
			4,
			1,
			9,
			12,
			14,
			2,
			0,
			6,
			10,
			13,
			15,
			3,
			5,
			8,
			2,
			1,
			14,
			7,
			4,
			10,
			8,
			13,
			15,
			12,
			9,
			0,
			3,
			5,
			6,
			11
		};
		private static byte[] E_TABLE = new byte[]
		{
			31,
			0,
			1,
			2,
			3,
			4,
			3,
			4,
			5,
			6,
			7,
			8,
			7,
			8,
			9,
			10,
			11,
			12,
			11,
			12,
			13,
			14,
			15,
			16,
			15,
			16,
			17,
			18,
			19,
			20,
			19,
			20,
			21,
			22,
			23,
			24,
			23,
			24,
			25,
			26,
			27,
			28,
			27,
			28,
			29,
			30,
			31,
			0
		};
		private static byte[] P_TABLE = new byte[]
		{
			15,
			6,
			19,
			20,
			28,
			11,
			27,
			16,
			0,
			14,
			22,
			25,
			4,
			17,
			30,
			9,
			1,
			7,
			23,
			13,
			31,
			26,
			2,
			8,
			18,
			12,
			29,
			5,
			21,
			10,
			3,
			24
		};
		private static int[] IP_TABLE = new int[]
		{
			57,
			49,
			41,
			33,
			25,
			17,
			9,
			1,
			59,
			51,
			43,
			35,
			27,
			19,
			11,
			3,
			61,
			53,
			45,
			37,
			29,
			21,
			13,
			5,
			63,
			55,
			47,
			39,
			31,
			23,
			15,
			7,
			56,
			48,
			40,
			32,
			24,
			16,
			8,
			0,
			58,
			50,
			42,
			34,
			26,
			18,
			10,
			2,
			60,
			52,
			44,
			36,
			28,
			20,
			12,
			4,
			62,
			54,
			46,
			38,
			30,
			22,
			14,
			6
		};
		private static int[] IPF_TABLE = new int[]
		{
			39,
			7,
			47,
			15,
			55,
			23,
			63,
			31,
			38,
			6,
			46,
			14,
			54,
			22,
			62,
			30,
			37,
			5,
			45,
			13,
			53,
			21,
			61,
			29,
			36,
			4,
			44,
			12,
			52,
			20,
			60,
			28,
			35,
			3,
			43,
			11,
			51,
			19,
			59,
			27,
			34,
			2,
			42,
			10,
			50,
			18,
			58,
			26,
			33,
			1,
			41,
			9,
			49,
			17,
			57,
			25,
			32,
			0,
			40,
			8,
			48,
			16,
			56,
			24
		};
		private static void XOR2(byte[] Out, int OutOffset, byte[] In1, byte[] In2)
		{
			for (int i = 0; i < 8; i++)
			{
				Out[i + OutOffset] = (In1[i] ^ In2[i]);
			}
		}
		private static void XOR(byte[] InA, int AOffset, byte[] InB, int BOffset, int int_0)
		{
			for (int i = 0; i < int_0; i++)
			{
				InA[i + AOffset] = (InA[i + AOffset] ^ InB[i + BOffset]);
			}
		}
		private static void ByteToBit(byte[] Out, int OutOffset, byte[] In, int InOffset, int bits)
		{
			for (int i = 0; i < bits; i++)
			{
				int num = (i >> 3) + InOffset;
				Out[i + OutOffset] = (byte)(In[num] >> (i & 7) & 1);
			}
		}
		private static void BitToByte(byte[] Out, int OutOffset, byte[] In, int bits)
		{
			Array.Clear(Out, OutOffset, bits >> 3);
			for (int i = 0; i < bits; i++)
			{
				int expr_19_cp_1 = (i >> 3) + OutOffset;
				Out[expr_19_cp_1] |= (byte)(In[i] << (i & 7));
			}
		}
		private static void CYCLELEFT(byte[] In, int InOffset, byte[] T, int int_0, int loop)
		{
			Array.Copy(In, InOffset, T, 0, loop);
			Array.Copy(In, InOffset + loop, In, InOffset, int_0 - loop);
			Array.Copy(T, 0, In, InOffset + int_0 - loop, loop);
		}
		private static void TRANSFORM(byte[] Out, int OutOffset, byte[] In, int InOffset, byte[] Table, int int_0, byte[] T)
		{
			for (int i = 0; i < int_0; i++)
			{
				T[i] = In[InOffset + (int)Table[i]];
			}
			Array.Copy(T, 0, Out, OutOffset, int_0);
		}
		private static void TRANSFORM_KEY(byte[] Out, int OutOffset, byte[] In, int InOffset, int[] Table, int int_0, byte[] T)
		{
			for (int i = 0; i < int_0; i++)
			{
				T[i] = In[Table[i]];
			}
			Array.Copy(T, 0, Out, OutOffset, int_0);
		}
		private static void Set_SubKey(byte[] pskey, byte[] Key, byte[] K, int KL, int KR, byte[] T)
		{
			DES.ByteToBit(K, 0, Key, 0, 64);
			DES.TRANSFORM_KEY(K, 0, K, 0, DES.PC1_TABLE, 56, T);
			for (int i = 0; i < 16; i++)
			{
				DES.CYCLELEFT(K, KL, T, 28, (int)DES.LOOP_TABLE[i]);
				DES.CYCLELEFT(K, KR, T, 28, (int)DES.LOOP_TABLE[i]);
				DES.TRANSFORM(pskey, i * 48, K, 0, DES.PC2_TABLE, 48, T);
			}
		}
		private static void SETKEY(byte[] SubKey, byte[] deskey, byte[] Key, int int_0, byte[] K, int KL, int KR, byte[] T)
		{
			Array.Clear(deskey, 0, 24);
			int num = (int_0 > 24) ? 24 : int_0;
			Array.Copy(Key, 0, deskey, 0, num);
			DES.Set_SubKey(SubKey, deskey, K, KL, KR, T);
		}
		private static void S_BOXF(byte[] Out, int OutOffset, byte[] In)
		{
			int num = 0;
			byte[] array = new byte[16];
			int i = 0;
			while (i < 8)
			{
				int num2 = ((int)In[num] << 1) + (int)In[5 + num];
				int inOffset = ((int)In[1 + num] << 3) + ((int)In[2 + num] << 2) + ((int)In[3 + num] << 1) + (int)In[4 + num];
				Array.Copy(DES.S_BOX, i * 64 + num2 * 16, array, 0, 16);
				DES.ByteToBit(Out, OutOffset, array, inOffset, 4);
				i++;
				num += 6;
				OutOffset += 4;
			}
		}
		private static void F_FUNCTION(byte[] In, int InOffset, byte[] Ki, byte[] MR, byte[] T)
		{
			DES.TRANSFORM(MR, 0, In, InOffset, DES.E_TABLE, 48, T);
			DES.XOR(MR, 0, Ki, 0, 48);
			DES.S_BOXF(In, InOffset, MR);
			DES.TRANSFORM(In, InOffset, In, InOffset, DES.P_TABLE, 32, T);
		}
		private static void DES_(byte[] Out, int OutOffset, byte[] In, int InOffset, byte[] pskey, int Type, byte[] M, byte[] MR, byte[] byte_0, int Li, int Ri, byte[] T)
		{
			byte[] array = new byte[48];
			DES.ByteToBit(M, 0, In, InOffset, 64);
			DES.TRANSFORM_KEY(M, 0, M, 0, DES.IP_TABLE, 64, T);
			if (Type == 1)
			{
				for (int i = 0; i < 16; i++)
				{
					Array.Copy(M, Ri, byte_0, 0, 32);
					Array.Copy(pskey, i * 48, array, 0, 48);
					DES.F_FUNCTION(M, Ri, array, MR, T);
					DES.XOR(M, Ri, M, Li, 32);
					Array.Copy(byte_0, 0, M, Li, 32);
				}
			}
			else
			{
				for (int j = 15; j >= 0; j--)
				{
					Array.Copy(M, Li, byte_0, 0, 32);
					Array.Copy(pskey, j * 48, array, 0, 48);
					DES.F_FUNCTION(M, Li, array, MR, T);
					DES.XOR(M, Li, M, Ri, 32);
					Array.Copy(byte_0, 0, M, Ri, 32);
				}
			}
			DES.TRANSFORM_KEY(M, 0, M, 0, DES.IPF_TABLE, 64, T);
			DES.BitToByte(Out, OutOffset, M, 64);
		}
		public static byte[] EncryptBytes(byte[] destBytes, byte[] byte_0, int type)
		{
			int num = destBytes.Length + 32;
			byte[] array = new byte[num];
			if (DES.Using_DES(array, ref num, destBytes, destBytes.Length, byte_0, byte_0.Length, 1) == 0)
			{
				return null;
			}
			byte[] array2 = new byte[num];
			Array.Copy(array, array2, array2.Length);
			return array2;
		}
		public static int Using_DES(byte[] Out, ref int OutLen, byte[] In, int InLen, byte[] Key, int keylen, int Type)
		{
			byte[] array = new byte[768];
			byte[] t = new byte[256];
			byte[] deskey = new byte[24];
			byte[] k = new byte[64];
			int kL = 0;
			int kR = 28;
			byte[] mR = new byte[48];
			byte[] m = new byte[64];
			byte[] byte_ = new byte[32];
			int li = 0;
			int ri = 32;
			byte[] array2 = new byte[9];
			byte[] array3 = new byte[8];
			int num = 0;
			int num2 = 0;
			byte[] array4 = new byte[8];
			if (Out.GetLength(0) == 0 || In.GetLength(0) == 0 || Key.GetLength(0) == 0 || InLen <= 0)
			{
				return 0;
			}
			if (Out.GetLength(0) < InLen + 32)
			{
				throw new ArithmeticException("Data buffer length is not enough!");
			}
			DES.SETKEY(array, deskey, Key, keylen, k, kL, kR, t);
			if (Type == 1)
			{
				int num3 = 8 - InLen % 8;
				int num4 = InLen + num3;
				byte[] array5 = new byte[num4];
				Array.Copy(In, 0, array5, 0, InLen);
				for (int i = 0; i < num3; i++)
				{
					array5[InLen + i] = (byte)num3;
				}
				DES.DES_(Out, num, array2, 0, array, Type, m, mR, byte_, li, ri, t);
				Array.Copy(Out, num, array3, 0, 8);
				num += 8;
				int j = 0;
				int num5 = num4 >> 3;
				while (j < num5)
				{
					Array.Copy(array5, num2, array4, 0, 8);
					DES.XOR2(array3, 0, array3, array4);
					DES.DES_(Out, num, array3, 0, array, Type, m, mR, byte_, li, ri, t);
					Array.Copy(Out, num, array3, 0, 8);
					j++;
					num += 8;
					num2 += 8;
				}
				OutLen = num4 + 8;
			}
			else
			{
				Array.Copy(In, num2, array2, 0, 8);
				num2 += 8;
				int l = 1;
				int num6 = InLen >> 3;
				while (l < num6)
				{
					DES.DES_(array3, 0, In, num2, array, Type, m, mR, byte_, li, ri, t);
					DES.XOR2(Out, num, array3, array2);
					Array.Copy(In, num2, array2, 0, 8);
					l++;
					num += 8;
					num2 += 8;
				}
				int num7 = (int)Out[num2 - 8 - 1];
				int num8 = num2 - 8;
				for (int n = 0; n < num7; n++)
				{
					Out[num8 - n - 1] = 0;
				}
				OutLen = num8 - num7;
			}
			return 1;
		}
	}
}
